package com.sywl.ytcx.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;


import javax.crypto.SecretKey;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;

import java.util.Calendar;
import java.util.Map;

public class JwtUtil {
    /**
    * JWT工具，
    * 用于生成token和解析token（不是特别的）
    * 注意：
    * 1.生成的token只能在本项目中使用，不能在其他项目中使用
    * 2.生成的token只能在本项目中解析，不能在其他项目中解析
    *
    * 生成令牌的代码我已经在UserServiceImpl里面写好了，登录接口登录了之后，用VerToken解析拿userId
    * userId补药写body或者params里或者头里面请求了
    *
    * VertokenUtil用法已写在VerTokenUtil类里
    *
    *
    * 长代码用法示例，用于加密其他内容：
    *
   Map<String, Object> tokenMap = new HashMap<>();  这一行是用来生成包含的token信息，补药直接返回token值
        Map<String, Object> payload = new HashMap<>();

        //这一行定义了token的payload，这个payload是用于存储用户信息的

        payload.put("user_id", 这里写你userid，或者其他需要加密的，记得改名字);
        payload.put("username", 这里写你的username,或者其他要加密的，记得改名);
        payload.put("cell_phone_num", 这里写你的电话号码，或者其他要加密的，记得改);


        //这里会比用户多put一个属性


        //生成JWT令牌   604800秒  7天，这是过期时间，写死就可以
        String token = JwtUtil.getToken(payload, 604800);
        *
        //这里要是怕出现有问题就try一下抛出去


     // 定义常量 这个参考UserServiceImpl里的
     private static final String ACCESS_TOKEN_KEY = "access_token";

     try {
            tokenMap.put("state", true);
            tokenMap.put("msg", "认证成功");
            tokenMap.put(ACCESS_TOKEN_KEY, token);//响应token    *这里的ACCESS_TOKEN_KEY是常量，所以要大写
        } catch (Exception e) {
            tokenMap.put("state", false);
            tokenMap.put("msg", "认证失败");
            tokenMap.put(ACCESS_TOKEN_KEY, null);//响应token    *
        }
    **/


    private static final String SIGNATURE =  "token!@#$%^7890123123123242890r7sd8fs0df8s09f8s90f8as0f8s0f8s0f8s09f8s0f8as90f8s09f8s09f890sf8s90f8s0f8as09ufw0ee9ufsdfjslfsofh238fywhfsfy982hrrwfy9wofhsofyhsfhwhfuihwiufhwifhuw";
    // 密钥需要超过256位字符
    private static SecretKey SECRET_KEY = Keys.hmacShaKeyFor(SIGNATURE.getBytes());
    /**
     * 生成token
     * @param map //传入payload
     * @param time //过期时间
     * @return 返回token
     */
    public static String getToken(Map<String,String> map,int time){
        JWTCreator.Builder builder = JWT.create();
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });
        Calendar instance = Calendar.getInstance();
        //604800一周
        instance.add(Calendar.SECOND,time);
        //一个token过期时间为七天
        builder.withExpiresAt(instance.getTime());
        return builder.sign(Algorithm.HMAC256(SIGNATURE)).toString();
    }

    /*=======================================*/
    /*
    注意：不要修改这里的代马，公用工具类不出问题就不要改
    在请求头里带token，名为 Authorization
    格式：Authorization: <token>
    生成出来参数是:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoi6Iul54WyIiwiaWQiOiIxIiwiY2VsbF9waG9uZV9udW0iOiIxODM3ODM0MzE2MSIsImV4cCI6MTc0MjM3ODUxNX0.5MWOo6tqzkMAQIuUx6CTuIHh25IEBVv05EMlIu2U5Fk
    这玩意是在本服务端生成的，不能在其他服务端使用
      在VerTokenUtil包，这是个静态类，不需要实例化，直接调用方法即可



    解析token的方法：VerTokenUtil.getUserId(Authorization)
    解析token的方法：VerTokenUtil.getUsername(Authorization)

                                _(\_/)
                             ,((((^`\
                            ((((  (6 \
                          ,((((( ,    \
      ,,,_              ,(((((  /"._  ,`,
     ((((\\ ,...       ,((((   /    `-.-'
     )))  ;'    `"'"'""((((   (
    (((  /            (((      \
     )) |                      |
    ((  |        .       '     |
    ))  \     _ '      `t   ,.')
    (   |   y;- -,-""'"-.\   \/
    )   / ./  ) /         `\  \
       |./   ( (           / /'
       ||     \\          //'|
       ||      \\       _//'||
       ||       ))     |_/  ||
       \_\     |_/          ||
       `'"                  \_\
                            `'"
     代马跑跑跑，咱们技术屌 -- 春卷：嘻嘻
     ------------------------

     * */
    private static final String SIGNATUREOnMes =  "token!@#$%^09f";

    /*
     *  消息token
     * */
    public static String getMesToken(Map<String,String> map,int time){
        JWTCreator.Builder builder = JWT.create();
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });
        Calendar instance = Calendar.getInstance();
        //604800一周
        instance.add(Calendar.SECOND,time);
        //过期时间为七天
        builder.withExpiresAt(instance.getTime());
        return builder.sign(Algorithm.HMAC256(SIGNATUREOnMes)).toString();
    }



    /**
     * 验证token
     * @param token
     */
    public static void verify(String token){
        JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
    }

    /**
     * 获取token中payload
     * @param token
     * @return
     */
    public static DecodedJWT getToken(String token){
        return JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
    }


    public static Jws<Claims> parseClaim(String token) {
        //解析token
        try {

            return Jwts.parser()
                    .verifyWith(SECRET_KEY)
                    .build()
                    .parseSignedClaims(token);
        }catch (Exception e){
//            e.printStackTrace();
            return null;
        }
    }

    public static JwsHeader parseHeader(String token) {
        return parseClaim(token).getHeader();
    }

    public static Claims parsePayload(String token) {
        return parseClaim(token).getPayload();
    }

}
